package com.evaluation_system.controller;

import ch.qos.logback.classic.Logger;
import com.evaluation_system.exception.*;
import com.evaluation_system.pojo.DTO.FilePageQueryDTO;
import com.evaluation_system.pojo.DTO.ScoreDTO;
import com.evaluation_system.pojo.DTO.UploaderDTO;
import com.evaluation_system.pojo.Result.PageResult;
import com.evaluation_system.pojo.Result.Result;
import com.evaluation_system.pojo.entity.*;
import com.evaluation_system.service.*;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.transaction.Transactional;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;

@RestController
@Slf4j
public class UserController {

    private static final Logger LOGGER = (Logger) LoggerFactory.getLogger(UserController.class);

    @Autowired
    private UploaderService uploadService;
    @Autowired
    private EvaluatorService evaluatorService;
    @Autowired
    private CheckerService checkerService;

    @GetMapping("/uploader/list")
    public Result<PageResult<saveFileInfo>> getUploaderPage(FilePageQueryDTO filePageQueryDTO) {
        Integer userId = uploadService.getUserId(filePageQueryDTO.getUsername());
        filePageQueryDTO.setId(userId);

        log.info("分页查询:{}", filePageQueryDTO);

        return Result.success(uploadService.readFile(filePageQueryDTO));
    }
//try-catch版本
//    @PostMapping("/uploader")
//    @Transactional
//    public Result<Object> handleUpload(UploaderDTO dto) {
//        try {
//            MultipartFile file= dto.getFile();
//            String filename = dto.getFilename();
//            String summary = dto.getSummary();
//            String username = dto.getUsername();
//            Object data = uploadService.encryptInfo(file, filename);
//            Integer userId = uploadService.getUserId(username);
//            Uploader uploader = uploadService.SelectById(userId);
//            if(uploader.getTruth()<60){
//                return Result.error("账户权限不足");
//            }
//            UploaderFile uploaderFile = UploaderFile.builder()
//                    .userId(userId)
//                    .fileName(filename)
//                    .summary(summary)
//                    .build();
//            Integer res=uploadService.FilenameByUploaderId(filename);
//            if(res!=null){
//                if(res==userId){
//                    uploadService.updateFile(uploaderFile);
//                }else{
//                    return Result.error("文件已存在");
//                }
//            }else{
//                uploadService.saveFile(uploaderFile);
//            }
//
//            //获得文件id，获得插入数据的文件id
//            Integer fileId = uploadService.getFileId(filename);
//            //文件id和摘要上链
//            int result = uploadService.commitBlockChain(fileId,summary,userId.toString());
//            //int result = 1;
//            //上链成功
//            if(result == 1)
//                System.out.println("上链成功");
//            return Result.success(data);
//        } catch (fileEncryptFailException e) {
//            LOGGER.info("加密失败", e);
//            return Result.error("加密失败: " + e.getMessage());
//        } catch (fileSaveFailException e) {
//            LOGGER.info("文件保存失败", e);
//            return Result.error("文件保存失败: " + e.getMessage());
//        }catch (commitChainFail e){
//            LOGGER.info("上链失败", e);
//            return Result.error("上链失败: " + e.getMessage());
//        } catch (Exception e) {
//            LOGGER.error("未知异常", e);
//            return Result.error("上传失败: " + e.getMessage());
//        }
//    }

    @PostMapping("/uploader")
    @Transactional
    public Result<Object> handleUpload(UploaderDTO dto) throws fileEncryptFailException, fileSaveFailException, commitChainFail {
        MultipartFile file = dto.getFile();
        String filename = dto.getFilename();
        String summary = dto.getSummary();
        String username = dto.getUsername();

        Object data = uploadService.encryptInfo(file, filename);
        Integer userId = uploadService.getUserId(username);
        Uploader uploader = uploadService.SelectById(userId);

        if(uploader.getTruth() < 60){
            LOGGER.info("账户权限不足，truth值: {}", uploader.getTruth());
            return Result.error("账户权限不足");
        }

        UploaderFile uploaderFile = UploaderFile.builder()
                .userId(userId)
                .fileName(filename)
                .summary(summary)
                .build();

        Integer res = uploadService.FilenameByUploaderId(filename);
        if(res != null) {
            if(res == userId) {
                uploadService.updateFile(uploaderFile);
            } else {
                LOGGER.info("文件已存在，上传者ID: {}", res);
                return Result.error("文件已存在");
            }
        } else {
            uploadService.saveFile(uploaderFile);
        }

        Integer fileId = uploadService.getFileId(filename);
        int result = uploadService.commitBlockChain(fileId, summary, userId.toString());
//        int result = 1;

        if(result == 1) {
            LOGGER.info("文件上链成功，fileId: {}", fileId);
        } else {
            throw new commitChainFail("上链失败，返回码: " + result);
        }

        return Result.success(data);
    }
//    @GetMapping("/evaluator/list")
//    public Result<Object> getEvaluatorList(
//            @RequestParam(defaultValue = "1") int page,
//            @RequestParam(defaultValue = "10") int size,
//            @RequestParam(required = false) String filename) {
//
//        try {
//            List<saveFileInfo> fileList = evaluatorService.readFile(size, page, filename);
//            return Result.success(fileList);
//        } catch (zeroPageException e) {
//            LOGGER.info("页数为0异常", e);
//            return Result.error("页数为0异常: " + e.getMessage());
//        } catch (Exception e) {
//            LOGGER.error("查询失败", e);
//            return Result.error("查询失败: " + e.getMessage());
//        }
//    }
    @GetMapping("/evaluator/list")
    public Result<PageResult<saveFileInfo>> getEvaluatorPage(FilePageQueryDTO filePageQueryDTO) {

        log.info("分页查询:{}", filePageQueryDTO);

        return Result.success(evaluatorService.readFile(filePageQueryDTO));
    }

//try-catch版本
//    @GetMapping("/evaluator/download/{id}")
//    public Result<Object> downloadPdf(@PathVariable("id") Integer id) {
//        try {
//            Evaluator evaluator = evaluatorService.SelectById(id);
//            if(evaluator.getTruth()<60){
//                return Result.error("账户权限不足");
//            }
//            byte[] pdfBytes = evaluatorService.getDownloadpdf(id);
//            pdfBytes = evaluatorService.decryptionPdf(pdfBytes, id);
//            String downloadUrl = evaluatorService.getDownloadUrl(id, pdfBytes);
//            return Result.success(downloadUrl);
//        } catch (downloadFailException e) {
//            LOGGER.error("下载失败", e);
//            return Result.error("下载失败: " + e.getMessage());
//        } catch (decryptedFailException e) {
//            LOGGER.error("解密失败", e);
//            return Result.error("解密失败: " + e.getMessage());
//        } catch (Exception e) {
//            LOGGER.error("下载异常", e);
//            return Result.error("下载异常: " + e.getMessage());
//        }
//    }

//    @GetMapping("/evaluator/download/{id}")
//    public Result<Object> evaluatorDownloadPdf(@PathVariable("id") Integer id,String userName)
//            throws downloadFailException, decryptedFailException {
//
//
//        Evaluator evaluator = evaluatorService.SelectByUserName(userName);
//        if(evaluator.getTruth() < 60){
//            LOGGER.warn("账户权限不足，truth值: {}", evaluator.getTruth());
//            return Result.error("账户权限不足");
//        }
//
//        // 提前记录可能抛出异常的操作
//        LOGGER.debug("开始处理PDF下载，ID: {}", id);
//        byte[] pdfBytes = evaluatorService.getDownloadpdf(id);
//
//        LOGGER.debug("开始解密PDF");
//        pdfBytes = evaluatorService.decryptionPdf(pdfBytes, id);
//
//        LOGGER.debug("生成下载URL");
//        String downloadUrl = evaluatorService.getDownloadUrl(id, pdfBytes);
//
//        return Result.success(downloadUrl);
//    }

    @GetMapping("/evaluator/download/{id}/{userName}")
    public void evaluatorDownloadPdf(
            @PathVariable("id") Integer id,
            @PathVariable("userName") String userName,
            HttpServletResponse response)
            throws IOException, downloadFailException, decryptedFailException {

        Evaluator evaluator = evaluatorService.SelectByUserName(userName);
        if (evaluator.getTruth() < 60) {
            LOGGER.warn("账户权限不足，truth值: {}", evaluator.getTruth());
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            response.setContentType("text/plain;charset=UTF-8");
            response.getWriter().write("账户权限不足");
            return;
        }

        LOGGER.debug("开始处理PDF下载，ID: {}", id);
        byte[] pdfBytes = evaluatorService.getDownloadpdf(id);

        LOGGER.debug("开始解密PDF");
        pdfBytes = evaluatorService.decryptionPdf(pdfBytes, id);

        // 设置响应头
        String fileName = "document_" + id + ".pdf";
        response.setContentType("application/pdf");
        response.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(fileName, "UTF-8") + "\"");
        response.setContentLength(pdfBytes.length);


        // 写入响应流
        try (OutputStream out = response.getOutputStream()) {
            out.write(pdfBytes);
            out.flush();
        }

    }

    //try-catch版本
//    @PostMapping("/evaluator/score")
//    public Result<Object> getScore(@RequestBody ScoreDTO dto) {
//        try {
//            Evaluator evaluator = evaluatorService.SelectById(dto.getEvaluator_id());
//            if(evaluator.getTruth()<60){
//                return Result.error("账户权限不足");
//            }
//            evaluatorService.insertIntoScore(dto.getFile_id(), dto.getEvaluator_id(), dto.getScore());
//            evaluatorService.commitBlockChain(dto.getFile_id(), dto.getScore(),dto.getEvaluator_id().toString());
//            return Result.success();
//        } catch (paramNullException e) {
//            LOGGER.error("参数为空", e);
//            return Result.error("参数为空: " + e.getMessage());
//        } catch (scoreErrorException e) {
//            LOGGER.error("评分错误", e);
//            return Result.error("评分不正确: " + e.getMessage());
//        } catch (Exception e) {
//            LOGGER.error("评分异常", e);
//            return Result.error("评分失败: " + e.getMessage());
//        }
//    }


//    @RequestMapping("/checker/list")
//    public Result<Object> getCheckerList(
//            @RequestParam(defaultValue = "1") int page,
//            @RequestParam(defaultValue = "10") int size,
//            @RequestParam(required = false) String filename) {
//        try {
//            List<saveFileInfo> fileList = checkerService.readFileForChecker(size, page, filename);
//            //
//            Integer total = checkerService.getTotal();
//            checkerResult checkRes = new checkerResult(fileList,total);
//            return Result.success(checkRes);
//        } catch (zeroPageException e) {
//            LOGGER.info("页数为0异常", e);
//            return Result.error("页数为0异常: " + e.getMessage());
//        } catch (Exception e) {
//            LOGGER.error("查询失败", e);
//            return Result.error("查询失败: " + e.getMessage());
//        }
//    }
    @PostMapping("/evaluator/score")
    @Transactional
    public Result<Object> getScore(@RequestBody ScoreDTO dto)
            throws Exception {

        // 权限检查（保持原逻辑）
        Evaluator evaluator = evaluatorService.SelectById(dto.getEvaluator_id());
        if(evaluator.getTruth() < 60){
            LOGGER.warn("账户权限不足，evaluator_id: {}，truth值: {}",
                    dto.getEvaluator_id(), evaluator.getTruth());
            return Result.error("账户权限不足");
        }

        // 记录操作日志（替代原catch中的日志）
        LOGGER.debug("开始处理评分，file_id: {}, evaluator_id: {}",
                dto.getFile_id(), dto.getEvaluator_id());

        // 执行业务操作（可能抛出已声明的异常）
        evaluatorService.insertIntoScore(dto.getFile_id(), dto.getEvaluator_id(), dto.getScore());
        evaluatorService.commitBlockChain(dto.getFile_id(), dto.getScore(), dto.getEvaluator_id().toString());

        return Result.success();
    }
    @GetMapping("/checker/list")
    public Result<PageResult<saveFileInfo>> getCheckerPage(FilePageQueryDTO filePageQueryDTO) {
        log.info("分页查询:{}", filePageQueryDTO);
        return Result.success(checkerService.getFile1(filePageQueryDTO));
    }

//    @RequestMapping("/checker/check")
//    public Result<Object> postChecker(
//            @RequestParam("file_id") Integer fileId,
//            @RequestParam("checker_id") Integer checkerId,
//            @RequestParam("checked") Integer checked) {
//        try {
////            //根据文件id从链上读取摘要
////            String summary = checkerService.queryBlockChain(fileId);
////            System.out.println("摘要是  "+summary);
//            Checker checker = checkerService.SelectById(checkerId);
//            if(checker.getTruth()<60){
//                return Result.error("账户权限不足");
//            }
//
//            //将文件id和checked数据上链
//            Integer returnValue = checkerService.commitBlockChain(fileId, checked,checkerId.toString());
//            if(returnValue == 1){
//                System.out.println("上链成功");
//            }
//
//            //更新数据库表中checked数据
//            checkerService.updateChecker(fileId, checkerId, checked);
//            return Result.success();
//        } catch (Exception e) {
//            LOGGER.info("服务器异常", e);
//            return Result.error("服务器异常: " + e.getMessage());
//        }
//    }

    @RequestMapping("/checker/check")
    @Transactional
    public Result<Object> postChecker(
            @RequestParam("file_id") Integer fileId,
            @RequestParam("checker_id") Integer checkerId,
            @RequestParam("checked") Integer checked)
            throws Exception {  // 声明抛出Exception以覆盖所有可能的异常

        // 权限检查（保持原逻辑不变）
        Checker checker = checkerService.SelectById(checkerId);
        if(checker.getTruth() < 60){
            LOGGER.warn("权限检查未通过，checker_id: {}，truth值: {}", checkerId, checker.getTruth());
            return Result.error("账户权限不足");
        }

        // 业务操作（原try块内容）
        Integer returnValue = checkerService.commitBlockChain(fileId, checked, checkerId.toString());
        if(returnValue == 1){
            LOGGER.debug("文件上链成功，file_id: {}", fileId);
            System.out.println("上链成功");
        }

        checkerService.updateChecker(fileId, checkerId, checked);
        return Result.success();
    }

    @GetMapping("/checker/download/{id}/{userName}")
    public void checkerDownloadPdf(@PathVariable("id") Integer id,
                                             @PathVariable("userName") String userName,
                                             HttpServletResponse response)
            throws IOException,downloadFailException, decryptedFailException {

        Checker checker = checkerService.SelectByUserName(userName);
        if(checker.getTruth() < 60){
            LOGGER.warn("账户权限不足，truth值: {}", checker.getTruth());
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            response.setContentType("text/plain;charset=UTF-8");
            response.getWriter().write("账户权限不足");
            return;
        }


        LOGGER.debug("开始处理PDF下载，ID: {}", id);
        byte[] pdfBytes = evaluatorService.getDownloadpdf(id);

        LOGGER.debug("开始解密PDF");
        pdfBytes = evaluatorService.decryptionPdf(pdfBytes, id);

        // 设置响应头
        String fileName = "document_" + id + ".pdf";
        response.setContentType("application/pdf");
        response.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(fileName, "UTF-8") + "\"");
        response.setContentLength(pdfBytes.length);


        // 写入响应流
        try (OutputStream out = response.getOutputStream()) {
            out.write(pdfBytes);
            out.flush();
        }
    }

}
